package com.iwhalecloud.bss.kite.cucc.order.operate;

import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts2;
import com.iwhalecloud.bss.kite.common.constant.ServiceOfferConsts;
import com.iwhalecloud.bss.kite.common.constant.TableConsts;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.common.util.SeqUtils;
import com.iwhalecloud.bss.kite.cucc.order.accept.constructor.DataConstructorManager;
import com.iwhalecloud.bss.kite.cucc.order.loader.IOrderInfoLoader;
import com.iwhalecloud.bss.kite.cucc.order.loader.InstLoaderFactory;
import com.iwhalecloud.bss.kite.dataservice.cache.DcPublicCache;
import com.iwhalecloud.bss.kite.dataservice.cache.DcSystemParamCache;
import com.iwhalecloud.bss.kite.dataservice.entity.DcPublic;
import com.iwhalecloud.bss.kite.dataservice.entity.OrderContactInfo;
import com.iwhalecloud.bss.kite.dataservice.entity.OrderItem;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.IInst;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferInst;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferObjInstRel;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.ProdInst;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.ProdInstAcctRel;
import com.iwhalecloud.bss.kite.dataservice.entity.order.DevStaffInfo;
import com.iwhalecloud.bss.kite.dataservice.entity.order.OrderDeposit;
import com.iwhalecloud.bss.kite.dataservice.entity.order.OrderItemChange;
import com.iwhalecloud.bss.kite.dataservice.mapper.inst.OfferInstMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.inst.OfferObjInstRelMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.inst.ProdInstAcctRelMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.inst.ProdInstMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.order.CustomerOrderMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.order.DevStaffInfoMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.order.OrderContactInfoMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.order.OrderDepositMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.order.OrderItemChangeMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.order.OrderItemMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.order.OrderItemRelMapper;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.util.ManagerUtils;
import com.iwhalecloud.bss.kite.order.client.api.operate.ICreateWithdrawOrderItemService;
import com.iwhalecloud.bss.kite.order.client.api.operate.IWithdrawOrderService;
import com.iwhalecloud.bss.kite.order.client.api.query.IWithdrawOrderQueryService;
import com.iwhalecloud.bss.kite.order.client.dto.OrderContainer;
import com.iwhalecloud.bss.kite.order.client.dto.OrderRequest;
import com.iwhalecloud.bss.kite.order.client.dto.WithdrawOrderRequest;
import com.ztesoft.bss.base.staticdata.CoreDataInteract;
import com.ztesoft.bss.base.staticdata.local.CoreDataInteractLocal;
import com.ztesoft.bss.common.bo.RoleInfo;
import com.ztesoft.bss.common.util.ContextUtil;
import com.ztesoft.bss.common.util.SpringUtil;
import com.ztesoft.bss.order.base.consts.BTables;
import com.ztesoft.bss.order.base.consts.IKeyValues;
import com.ztesoft.bss.order.base.consts.KeyValues;
import com.ztesoft.bss.order.base.consts.KeyValuesLocal;
import com.ztesoft.bss.order.base.orm.conf.BusiConfigTables;
import com.ztesoft.bss.order.dto.OrderItemRel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

@Service("withdrawOrderServiceOfOrder")
public class WithdrawOrderService implements IWithdrawOrderService {

    @Autowired
    private ICreateWithdrawOrderItemService createWithdrawOrderItemService;

    @Autowired
    private IWithdrawOrderQueryService withdrawOrderQueryService;

    @Autowired
    private IOrderInfoLoader orderInfoLoader;

    @Autowired
    private CustomerOrderMapper customerOrderMapper;

    @Autowired
    private OrderItemMapper orderItemMapper;

    // @Autowired
    // private OrderItemAttrMapper orderItemAttrMapper;

    @Autowired
    private OrderItemRelMapper orderItemRelMapper;

    @Autowired
    private OrderItemChangeMapper orderItemChangeMapper;

    @Autowired
    private ProdInstMapper prodInstMapper;

    @Autowired
    private ProdInstAcctRelMapper prodInstAcctRelMapper;

    @Autowired
    private DevStaffInfoMapper devStaffInfoMapper;

    @Autowired
    private OrderContactInfoMapper orderContactInfoMapper;

    @Autowired
    private OrderDepositMapper orderDepositMapper;

    @Override
    public WithdrawOrderRequest createWithdrawOrderRequest(OrderRequest orderRequest, List<String> askIds,
        String oldCustOrderId, String undoReason) {
        WithdrawOrderRequest request = new WithdrawOrderRequest();
        KiteBeanUtils.copyProperties(orderRequest, request);
        request.setOldCustOrderId(oldCustOrderId);
        request.setAskIds(askIds);
        request.setUndoReason(undoReason);
        this.setAskIds(request);
        return request;
    }

    @Override
    public void setAskIds(WithdrawOrderRequest request) {
        List<OrderItem> oldOrderItems = this.withdrawOrderQueryService.listOldOrderItems(request.getOldCustOrderId(),
            request.getCustId(), request.getAskIds());
        if (KiteListUtils.isEmpty(oldOrderItems)) {
            ErrorConsts.WITHDRAW_ORDER_CHECK.throwOut(request.getOldCustOrderId());
        }
        request.setDeleteOrderItems(oldOrderItems);

        List<String> oldItemIds = new ArrayList<>();
        oldOrderItems.forEach(t -> {
            oldItemIds.add(t.getOrderItemId());
        });
        request.setOrderItemIds(oldItemIds);
        // askid去重设置 askIds
        oldOrderItems = distinctOrderItemByAskId(oldOrderItems);

        List<String> retAskIds = new ArrayList<>();
        if (!KiteListUtils.isEmpty(oldOrderItems)) {
            for (OrderItem orderItem : oldOrderItems) {
                retAskIds.add(orderItem.getAskId());
            }
            request.setAskIds(retAskIds);
        }
    }

    private List<OrderItem> distinctOrderItemByAskId(List<OrderItem> allOrderItems) {
        Set<String> askIdList = new HashSet<String>();
        List<OrderItem> orderItems = new ArrayList<OrderItem>();
        for (OrderItem orderItem : allOrderItems) {
            String askId = orderItem.getAskId();
            if (KiteStringUtils.isEmpty(askId)) {
                continue;
            }
            if (!askIdList.contains(askId)) {
                askIdList.add(askId);
                orderItems.add(orderItem);
            }
        }
        return orderItems;
    }

    @Override
    public void checkCanWithdraw(WithdrawOrderRequest request) {
        List<OrderItem> orderItems = withdrawOrderQueryService.listWithdrawOrderItems(request.getOrderItemIds(),
            request.getCustId());
        if (!KiteListUtils.isEmpty(orderItems)) {
            List<String> orderItemIds = new ArrayList<>();
            orderItems.forEach((item) -> orderItemIds.add(item.getOldOrderItemId()));

            String ids = orderItemIds.stream().collect(Collectors.joining(","));
            ErrorConsts.WITHDRAW_REPEATED_CHECK.throwOut(ids);
        }
    }

    @Override
    public boolean checkWithdrew(String orderItemId, String custId) {
        List<OrderItem> withdrawOrderItems = withdrawOrderQueryService
            .listWithdrawOrderItems(Arrays.asList(orderItemId), custId);
        // 非空即已经撤单
        return KiteListUtils.isNotEmpty(withdrawOrderItems);
    }

    @Override
    public void withdrawAsk(WithdrawOrderRequest request) {
        // 取后面的askid
        List<String> latterAskIds = withdrawOrderQueryService.listLatterAskIds(String.join(",", request.getAskIds()),
            request.getCustId());
        // 拉单
        this.loadAskIds(request, latterAskIds);

        //撤单时，产品拉销售品订单撤单
        this.checkAddAsk(request);

        this.cancelNotCommitWithdrawOrder(request);

        this.loadOldOrderInfos(request, request.getAskIds());
//            KeyConsts.IFTRUE_T.equals(request.getNoMergedFlag()) ? Boolean.TRUE : Boolean.FALSE
        // TODO 撤单规则埋点开始

        //设置新的ask_id
        request.setNewAskId(SeqUtils.genOrderItemId(request.getLanId()));
        // TODO 撤单规则埋点结束
        this.doWithdraw(request);

        this.clearBackfillStaffId(request);
    }

    private void doWithdraw(WithdrawOrderRequest request) {
        boolean isSetMain = false;
        Map<String, String> orderItemIds_ = new HashMap<>();
        List<OrderItem> orderItems = OrderContainer.ofRequest(request).listOrderItems();
        for (int i = orderItems.size() - 1; i >= 0; i--) {
            OrderItem orderItem = orderItems.get(i);
            // 修正单不做处理,改为撤单做处理
//            if (CoreDataInteract.EVT_C_0003_1100.equals(orderItem.getOperType())) {
//                continue;
//            }
            // 撤单本身不做处理
            if (CoreDataInteract.EVT_C_0003_1200.equals(orderItem.getOperType())
                && KeyValues.UNDO_FLAG_T.equals(orderItem.getUndoFlag())) {
                continue;
            }
            if (this.checkWithdrew(orderItem.getOrderItemId(), orderItem.getBelongCustId())) {
                continue;
            }
            if (!orderItemIds_.containsKey(orderItem.getOrderItemId())
                && KiteStringUtils.isNotEmpty(orderItem.getOrderItemId())) {
                orderItemIds_.put(orderItem.getOrderItemId(), orderItem.getBelongCustId());
            }

            String orderItemId = orderItem.getOrderItemId();
            String oldOrderItemId = orderItem.getOldOrderItemId();
            if (!orderItemIds_.containsKey(oldOrderItemId) && KiteStringUtils.isNotEmpty(oldOrderItemId)) {
                orderItemIds_.put(oldOrderItemId, orderItem.getBelongCustId());
            }
            if (this.isInvalid(request, orderItem)) {
                // 不是正常受理单，并且原订单项编号不等于订单项编号，就不处理。因为存在原单是缓装状态，也让工单撤单的情况出现。
                if (!CoreDataInteract.EVT_C_0003_1000.equals(orderItem.getOperType())
                    && !orderItem.getOrderItemId().equals(oldOrderItemId)) {
                    continue;
                }
            }
            String newOrderItemId = "";
            if (!isSetMain && orderItem.getOrderItemId().equals(orderItem.getAskId())) {
                newOrderItemId = request.getNewAskId();
                isSetMain = true;
            }
            else {
                // TODO 生成新订单项ID
                 newOrderItemId = SeqUtils.genOrderItemId(request.getLanId());
            }

            if (!orderItemIds_.containsKey(newOrderItemId) && KiteStringUtils.isNotEmpty(newOrderItemId)) {
                orderItemIds_.put(newOrderItemId, orderItem.getBelongCustId());
            }

            // TODO 生成撤单订单项
            OrderItem newIterm = createWithdrawOrderItemService.createWithdrawOrderItems(request, orderItemId, newOrderItemId, request.getNewAskId(),
                request.getUndoReason(), request.getRemark(), request.getStaffId());
            createWithdrawOrderItemService.createWithdrawOrderItemChanges(request, orderItemId, request.getStaffId(), newIterm);

            request.getOrderContainer().getOrderDepositMap().remove(orderItem.getOrderItemId());

        }
        // 撤单实例值还原处理
        DataConstructorManager.buildInstData(request, OrderContainer.ofRequest(request).listOrderItemChanges());
    }

    private void checkAddAsk(WithdrawOrderRequest request) {
        if (!KeyConsts.SERVICE_WITHDRAW.equals(request.getServiceOfferId())) {
            return;
        }
        List<OrderItem> deleteOrderItems = request.getDeleteOrderItems();
        // 如果是单手机套餐撤单跳过此环节不拉单

        if (containPhone(request)) {
            return;
        }
        String oldCustOrderId = request.getOldCustOrderId();
        //获取所有在途的订单
        OrderItemMapper orderItemMapper = SpringUtil.getBean(OrderItemMapper.class);
        List<OrderItem> orderItems = orderItemMapper.listByCustOrderId(oldCustOrderId, request.getCustId());
        List<OrderItem> orderNew = new ArrayList<>();
        for (OrderItem orderItem : deleteOrderItems) {
            String objId = orderItem.getObjId();
            OfferObjInstRelMapper mapper = SpringUtil.getBean(OfferObjInstRelMapper.class);
            Example em = new Example(OfferObjInstRel.class);
            em.createCriteria().andEqualTo("mcompInstId", objId);
            List<OfferObjInstRel> offerObjInstRels = mapper.selectByExample(em);
            offerObjInstRels.forEach(t -> {
                orderNew.addAll(orderItems.stream().filter(order -> {
                    return (order.getObjId().equals(t.getOfferInstId()));
                }).collect(Collectors.toList()));
            });
        }
        // 对比orderNew与 deleteOrderItems
        List<String> orderItemIds = request.getOrderItemIds();
        orderItemIds.forEach(str -> {
            Iterator<OrderItem> iterator = orderNew.iterator();
            while (iterator.hasNext()) {
                OrderItem orderItem = iterator.next();
                if (orderItem.getOrderItemId().equals(str) || isNotCancle(orderItem)) {
                    iterator.remove();
                }
            }
        });

        orderNew.forEach(orderItem -> {
            orderItemIds.add(orderItem.getOrderItemId());
            OrderContainer.ofRequest(request).addOrderItem(orderItem);
        });
        orderNew.addAll(deleteOrderItems);
        request.setDeleteOrderItems(orderNew);
        request.setOrderItemIds(orderItemIds);
    }

    private  boolean isNotCancle(OrderItem orderItem) {
        String orderItemId = orderItem.getOrderItemId();
        OrderItemMapper mapper = SpringUtil.getBean(OrderItemMapper.class);
        Example em = new Example(OrderItem.class);
        em.createCriteria().andEqualTo("oldOrderItemId", orderItemId);
        List<OrderItem> orderItems = mapper.selectByExample(em);
        if (KiteListUtils.isNotEmpty(orderItems)) {
            return true;
        }
        return  false;
    }

    /**
     * 1、拉修正单原单 2、加载合并加具有加装关系的产品的订单项 3、加装关联的订单项或者被关联的订单限。主要用于有关联促销的情况。
     *
     * @param request
     * @param askIds
     * @return
     */
    private void loadAskIds(WithdrawOrderRequest request, List<String> askIds) {
        // 拉修正单原单（修正单不能撤单，这里拉取不到ask_id，noMergedFlag始终为false）
        List<String> askIdXZs = this.withdrawOrderQueryService.listFacthAskIds(askIds, request.getCustId());
        // 如果askIds==_askIds，可以认为是不需要做合并的（有修正单需要合并订单项，把修正的订单项合并到原单订单项上）
        boolean noMergedFlag = (askIds.containsAll(askIdXZs) ? true : false);
        request.setNoMergedFlag(noMergedFlag);
        // 加载合并加具有加装关系的产品的订单项
        if (KiteListUtils.isNotEmpty(askIds)) {
            List<String> relaAskIds = this.withdrawOrderQueryService.listRelativeAskIds(askIds, request.getCustId());
            if (KiteListUtils.isNotEmpty(relaAskIds)) {
                askIds.addAll(relaAskIds);
            }
            // 加装关联的订单项或者被关联的订单限。主要用于有关联促销的情况。
            askIds = this.withdrawOrderQueryService.listRelCompInstIdAskIds(askIds, request.getCustId());
            request.getAskIds().addAll(askIds);
            request.setAskIds(request.getAskIds().stream().distinct().collect(Collectors.toList()));
        }

        // 更新订单项, 补充修正单
        List<OrderItem> withdrawOrderItems = withdrawOrderQueryService
                .listAllOrderItems(askIds, request.getCustId());
        request.setDeleteOrderItems(withdrawOrderItems);
        List<String> orderItems = withdrawOrderItems.stream()
                .map(s -> s.getOrderItemId())
                .collect(Collectors.toList());
        request.setOrderItemIds(orderItems);
        withdrawOrderItems.forEach(t -> {
            OrderContainer.ofRequest(request).addOrderItem(t);
        });
    }

    private void loadOldOrderInfos(WithdrawOrderRequest request, List<String> askIds) {
        if (KiteListUtils.isEmpty(askIds)) {
            return;
        }
        String custId = request.getCustId();
        List<String> orderItemIds = this.withdrawOrderQueryService.listOrderItemIdsByAskIds(askIds,
            request.getCustId());
        for (String orderItemId : orderItemIds) {
            orderInfoLoader.loadOldOrderInfos(request, orderItemId, custId);
        }

        // 是否合并修正单
        if (request.getNoMergedFlag()) {
            return;
        }

        // 1.重新计算订单项变动
        resetItemChg(request);
        // 2.筛选掉修正单订单项
        resetOrderItem(request);
    }

    private Boolean containPhone(WithdrawOrderRequest request) {
        List<String> askIds = request.getAskIds();
        List<OrderItem> deleteOrderItems = request.getDeleteOrderItems();
        if (KiteListUtils.isEmpty(askIds)) {
            return false;
        }
        for (OrderItem orderItem :deleteOrderItems) {
            String objId = orderItem.getObjId();
            // objId为基础销售品的offer_inst_id
            OfferInstMapper offerInstMapper = SpringUtil.getBean(OfferInstMapper.class);
            OfferInst offerInst = offerInstMapper.selectByPrimaryKey(objId);
            if (offerInst.getOfferId().equals("302020966")) {
                return true;
            }
        }

        return false;
    }
    /**
     * 筛选掉修正单的订单项
     * @param request
     */
    private void resetOrderItem(WithdrawOrderRequest request) {
        Map<String, OrderItem> orderItemMap = new HashMap<>();
        request.getOrderContainer().getOrderItemMap().forEach((key, value) -> {
            if (!CoreDataInteract.EVT_C_0003_1100.equals(value.getOperType())) {
                orderItemMap.put(key, value);
            }
        });
        request.getOrderContainer().setOrderItemMap(orderItemMap);
    }

    /**
     * 重新计算订单项变动
     *
     * @param request
     */
    private void resetItemChg(WithdrawOrderRequest request) {
        List<OrderItemChange> orderItemChanges = OrderContainer.ofRequest(request).listOrderItemChanges();
        Map<String, List<OrderItemChange>> itemChgsMap = new HashMap<>();
        // 对订单项变动进行分组，key为tableName_instId
        orderItemChanges.forEach(t -> {
            String key = ManagerUtils.join(t.getTableName(), ManagerUtils.CHAR_UNDERLINE, t.getInstId());
            itemChgsMap.computeIfAbsent(key, k -> new ArrayList<>()).add(t);
        });

        Map<String, List<OrderItemChange>> itemChgMap = new HashMap<>();
        itemChgsMap.forEach((key, value) -> {
            // fieldName为空，即为A/D
            List<OrderItemChange> itemChanges = value.stream().filter(t -> KiteStringUtils.isEmpty(t.getFieldName()))
                .collect(Collectors.toList());
            if (!KiteListUtils.isEmpty(itemChanges)) {
                OrderItemChange itemChg = itemChanges.stream()
                    .filter(t -> ActionType.A.name().equals(t.getActionType())).findFirst().orElse(itemChanges.get(0));
                putItemChg(request, itemChgMap, itemChg);
            }
            // 属性的修改,如果是同属性的大于1条，取时间较早的那条变动
            else {
                Map<String, List<OrderItemChange>> tempChgMap = KiteListUtils.groupBy(value, "fieldName");
                tempChgMap.forEach((k, v) -> {
                    sortItemChgs(v);
                    OrderItemChange itemChg = v.get(0);
                    putItemChg(request, itemChgMap, itemChg);
                });
            }
        });
        request.getOrderContainer().setOrderItemChangeMap(itemChgMap);
    }

    private void putItemChg(WithdrawOrderRequest request, Map<String, List<OrderItemChange>> itemChgMap,
        OrderItemChange itemChg) {
        // 如果是修正订单项，取原订单项id
        OrderItem orderItem = OrderContainer.ofRequest(request).getOrderItem(itemChg.getOrderItemId());
        if (CoreDataInteract.EVT_C_0003_1100.equals(orderItem.getOperType())) {
            itemChg.setOrderItemId(orderItem.getOldOrderItemId());
        }
        itemChgMap.computeIfAbsent(itemChg.getOrderItemId(), kk -> new ArrayList<>()).add(itemChg);
    }

    private List<OrderItemChange> sortItemChgs(List<OrderItemChange> itemChanges) {
        Collections.sort(itemChanges, new Comparator<OrderItemChange>() {
            @Override
            public int compare(OrderItemChange o1, OrderItemChange o2) {
                if (Objects.isNull(o1.getHandleTime()) && Objects.isNull(o2.getHandleTime())) {
                    // 不交换顺序
                    return 0;
                }
                if (Objects.isNull(o1.getHandleTime())) {
                    // 交换顺序，空值排后面
                    return 1;
                }
                if (Objects.isNull(o2.getHandleTime())) {
                    // 不交换顺序，空值排后面
                    return -1;
                }
                return o1.getHandleTime().compareTo(o2.getHandleTime());
            }
        });
        return itemChanges;
    }

    @Override
    public void cancelNotCommitWithdrawOrder(WithdrawOrderRequest request) {
        String custId = request.getCustId();
        List<String> askIds = request.getAskIds();
        // 查状态为101100和101300的撤单订单项或修正单订单项的askid
        List<String> withdrawAskIds = this.withdrawOrderQueryService.listNotCommitWithdrawAskIds(askIds, custId);
        if (KiteListUtils.isNotEmpty(withdrawAskIds)) {
            for (String askId : withdrawAskIds) {
                List<String> askids = this.withdrawOrderQueryService.listLatterAsksNotCommit(askId,
                    request.getRemark(), custId);
                // 加载订单项
                this.loadOldOrderInfos(request, askids);
                // 处理未提交变动信息
                this.dealNotCommmitOrderItemChanges(request);
                // 加载销售品实例
                this.loadOfferInsts(request);
                // 取消未提交订单项
                this.cancelNotCommitWithdrawOrderItems(request);
            }
        }
    }

    private void dealNotCommmitOrderItemChanges(WithdrawOrderRequest request) {
        List<OrderItem> orderItems = OrderContainer.ofRequest(request).listOrderItems();
        for (OrderItem orderItem : orderItems) {
            if (this.isInvalid(request, orderItem)) {
                continue;
            }
            String status = orderItem.getStatusCd();
            if (!(CoreDataInteract.EVT_0001_101100.equals(status) || CoreDataInteract.EVT_0001_101300.equals(status))) {
                ErrorConsts.CANCEL_WITHDRAW_ORDER_ITEM_ERROR.throwOut(orderItem.getOrderItemId());
            }
            // 修正处理
            if (KeyConsts.OPER_TYPE_EVT_C_0011_1100.equals(orderItem.getOperType())) {
                this.dealModOrderItemChange(request, orderItem);
            }
            if (KeyConsts.OFFER_TYPE_10.equals(orderItem.getOfferKind())) {
                this.dealProdOrderItemChange(request, orderItem);
            }

            // TODO 取消订单规则埋点
            // AttrInvoker.onCancel(param);
        }
    }

    private void loadOfferInsts(WithdrawOrderRequest request) {
        // 加载实例
        String tableName = TableConsts.OfferInst.getTableName();
        List<OrderItem> orderItems = OrderContainer.ofRequest(request).listOrderItems();
        for (OrderItem orderItem : orderItems) {
            InstLoaderFactory.getInstLoader(tableName).loadInst(request, TableConsts.OfferInst.getTableName(),
                orderItem.getObjId(), orderItem.getBelongCustId());
        }
    }

    private void cancelNotCommitWithdrawOrderItems(WithdrawOrderRequest request) {
        if (Objects.isNull(request.getOrderContainer().getOrderItemMap())) {
            return;
        }
        Iterator<OrderItem> it = OrderContainer.ofRequest(request).listOrderItems().iterator();
        while (it.hasNext()) {
            OrderItem orderItem = it.next();
            if (!this.isInvalid(request, orderItem)) {
                continue;
            }
            // 过户业务场景
            String serviceOfferId = DcSystemParamCache.getDcParamVal("TRANSFER_COMPATIBLE_SERVICE");
            if (!KiteStringUtils.isEmpty(serviceOfferId)
                && Arrays.asList(serviceOfferId.split(",")).contains(orderItem.getServiceOfferId())
                || ServiceOfferConsts.SERVICE_OFFER_MERGE.equals(request.getServiceOfferId())) {
                // 获取原单变动信息
                List<OrderItemChange> changes = request.getOrderContainer().getOrderItemChangeMap()
                    .get(orderItem.getOrderItemId());
                if (KiteListUtils.isEmpty(changes)) {
                    continue;
                }
                // TODO 根据原单变动还原
                for (OrderItemChange change : changes) {
                    change.setFieldValue(change.getOldFieldValue());

                    if ("XX".equals(change.getInstStateChg()) || (!KiteStringUtils.isEmpty(change.getInstStateChg())
                        && change.getInstStateChg().startsWith("K"))) {
                        // TODO 实例actionType设置为K
                        this.updateInstAttr(request, change, "actionType", ActionType.K.name());
                    }

                    // TODO 取消过户订单，实例更新操作
                    // 根据实例变动获取新客户ID，为空则客户没有发生变动
                    String custId = this.getCustIdByOrderItemChange(changes, Boolean.TRUE);
                    IInst inst = InstLoaderFactory.getInstLoader(change.getTableName()).loadInst(request,
                        change.getTableName(), change.getInstId(), "");
                    String instOwnerCustId = Optional.ofNullable(inst).map(IInst::getOwnerCustId).orElse("");
                    if (KiteStringUtils.isEmpty(custId)
                        && StringUtils.equals(orderItem.getBelongCustId(), instOwnerCustId)) {
                        // 客户没变动
                        // 如果实例的新增则删除，否则回退变动
                        boolean isInvalid = false;
                        if ("XX".equals(change.getInstStateChg())) {
                            // 设置实例this.setOperFlag(KeyValues.OPER_FLAG_D);
                            isInvalid = true;
                        }
                        String instActionType = inst.getActionType();
                        if ((KeyValues.ACTION_TYPE_M.equals(instActionType) && "DD".equals(change.getInstStateChg()))
                            || KeyValues.ACTION_TYPE_A.equals(instActionType)
                                && "AD".equals(change.getInstStateChg())) {
                            isInvalid = true;
                        }
                        if (KiteStringUtils.isNotEmpty(change.getInstStateChg())
                            && "AD".equals(change.getInstStateChg())) {
                            isInvalid = false;
                        }
                        if (!isInvalid) {
                            if (ActionType.A.name().equals(instActionType)) {
                                // 删除实例
                                this.updateInstAttr(request, change, "ActionType", ActionType.D.name());
                            }
                            else {
                                // 回退实例字段变动
                            }
                        }
                    }
                    else {
                        // 客户有变动
                        if (KiteStringUtils.isEmpty(custId)) {
                            custId = request.getCustId();
                        }

                        // TODO 客户变动，实例非新增，则要生成原客户实例信息

                        // TODO 客户变动，都要生成删除新客户实例信息
                    }
                }
            }
            // TODO 保存删除订单项和客户订单属性数据的客户订单，入库操作才一并处理
            request.addDeleteOrderItem(orderItem);
            // TODO 删除审批数据
            // this.deleteApprove(orderItem.getOrderItemId(), orderItem.getBelongCustId());
            // TODO 取消终端回收信息
            // this.deleteRecycleInfo(orderItem.getCustOrderId(), orderItem.getObjId(), orderItem.getBelongCustId());
            // TODO 清空受理备注信息
            this.clearReason(orderItem.getCustOrderId(), orderItem.getBelongCustId());
        }
    }

    /**
     * 更新实例属性
     *
     * @param request
     * @param change
     * @param attrName
     * @param attrValue
     */
    private void updateInstAttr(WithdrawOrderRequest request, OrderItemChange change, String attrName,
        String attrValue) {
        String tableName = change.getTableName();
        String instId = change.getInstId();
        String custId = change.getCustId();
        IInst inst = InstLoaderFactory.getInstLoader(tableName).loadInst(request, tableName, instId, custId);
        KiteBeanUtils.setValueByName(inst, attrName, attrValue);
    }

    /**
     * 根据订单变动信息获取客户ID
     *
     * @param orderItemChanges
     * @param flag: true 返回新客户ID ，false : 返回老客户ID 分片字段改造过户修改 modify by xiao.xuzhang
     * @return
     */
    private String getCustIdByOrderItemChange(List<OrderItemChange> orderItemChanges,
        boolean flag) {
        String cust_id = "";
        for (OrderItemChange orderItemChange : orderItemChanges) {
            if (StringUtils.equals(orderItemChange.getTableName(), BusiConfigTables.PROD_INST_ACCT_REL.name())) {
                Example example = new Example(ProdInstAcctRel.class);
                example.createCriteria().andEqualTo("prodInstAcctRelId", orderItemChange.getInstId());
                ProdInstAcctRel prodInstAcctRel = this.prodInstAcctRelMapper.selectOneByExample(example);
                if (!KiteStringUtils.isEmpty(prodInstAcctRel.getOwnerCustId())) {
                    return prodInstAcctRel.getOwnerCustId();
                }
            }
            if (!StringUtils.equals(orderItemChange.getFieldName(), BTables.PROD_INST.owner_cust_id)) {
                continue;
            }

            if (flag) {
                cust_id = orderItemChange.getFieldValue();
                break;
            }
            else {
                cust_id = orderItemChange.getOldFieldValue();
                break;
            }

        }

        return cust_id;
    }

    /**
     * 检查实例是否被其他订单项订购
     *
     * @param orderItemId
     * @param ownerCustId
     * @return
     */
    private boolean checkOrderByOtherOrderItem(String orderItemId, String ownerCustId, String instId) {
        String count = this.orderItemMapper.checkOrderByOtherOrderItem(orderItemId, ownerCustId, instId);
        return !"0".equals(count);
    }

    private boolean checkOrderItemConstructs(String orderItemId, String ownerCustId) {
        List<String> constructs = this.orderItemMapper.listOrderItemConstructs(orderItemId, ownerCustId);
        return KiteListUtils.isNotEmpty(constructs);
    }

    @SuppressWarnings("deprecation")
    private void dealProdOrderItemChange(WithdrawOrderRequest request, OrderItem orderItem) {
        // 判断是否带宽型产品 TODO 增加配置
        boolean flagPriv = false; // 先赋值为fals ,有权限
        String bandwithProdId = DcSystemParamCache.getDcParamVal("BANDWITH_RPOD_ID");
        if (!KiteStringUtils.isEmpty(bandwithProdId)
            && Arrays.asList(bandwithProdId.split(",")).contains(orderItem.getApplyObjSpec())) {
            List<RoleInfo> roleInfos = ContextUtil.getLoginInfo().getUserRoles();
            String roleId = "";
            // 增加非空判断
            if (!KiteListUtils.isEmpty(roleInfos)) {
                for (RoleInfo roleInfo : roleInfos) {
                    roleId = roleInfo.getSysRoleId().toString();
                    if ("500001".equals(roleId)) {
                        flagPriv = true;
                        break;
                    }
                }
            }
        }
        if (flagPriv) {
            ErrorConsts.CANCEL_BANDWITH_PROD_ORDER_ITEM_ERROR.throwOut();
        }
        if (ServiceOfferConsts.SERVICE_OFFER_ORDER.equals(orderItem.getServiceOfferId())
            && KeyConsts.UNDO_FLAG_F.equals(orderItem.getUndoFlag())) {
            if (this.checkOrderItemConstructs(orderItem.getOrderItemId(), orderItem.getBelongCustId())) {
                ErrorConsts.CANCEL_FORBIDDEN_ERROR.throwOut(orderItem.getOrderItemId());
            }
            List<OrderItemChange> orderItemChanges = request.getOrderContainer().getOrderItemChangeMap()
                .get(orderItem.getOrderItemId());
            if (!KiteListUtils.isEmpty(orderItemChanges)) {
                for (OrderItemChange change : orderItemChanges) {
                    if (!KiteStringUtils.isEmpty(change.getInstId())
                        && change.getCompInstId().equals(orderItem.getObjId())
                        && ActionType.A.name().equals(change.getActionType())) {
                        ProdInst prodInst = prodInstMapper.getProdInstByProdInstId(change.getInstId(),
                            request.getCustId());
                        List<DcPublic> dcPublics = DcPublicCache.getByPcode("15090801", "T");
                        // 在用不能取消
                        if (KeyConsts.STATE_USING.equals(prodInst.getStatusCd()) && !KiteListUtils.isEmpty(dcPublics)) {
                            orderItemChanges.remove(change);
                            break;
                        }
                        else if (this.checkOrderByOtherOrderItem(orderItem.getOrderItemId(),
                            orderItem.getBelongCustId(), change.getCompInstId())) {
                            orderItemChanges.remove(change);
                            break;
                        }
                    }
                }
            }
        }
    }

    private void dealModOrderItemChange(WithdrawOrderRequest request, OrderItem orderItem) {
        List<OrderItemChange> changes = request.getOrderContainer().getOrderItemChangeMap()
            .get(orderItem.getOrderItemId());
        if (!KiteListUtils.isEmpty(changes)) {
            for (OrderItemChange change : changes) {
                if (!KiteStringUtils.isEmpty(change.getInstId()) && change.getCompInstId().equals(orderItem.getObjId())
                    && ActionType.A.name().equals(change.getActionType())) {
                    String oldOrderItemId = orderItem.getOldOrderItemId();

                    Example example = new Example(OrderItem.class);
                    example.createCriteria().andEqualTo("orderItemId", oldOrderItemId).andEqualTo("belongCustId",
                        request.getCustId());
                    OrderItem oldOrderItem = orderItemMapper.selectOneByExample(example);

                    List<DcPublic> dcPublics = DcPublicCache.get("15082001");
                    if (Objects.nonNull(oldOrderItem) && !KiteListUtils.isEmpty(dcPublics)
                        && "T".equals(dcPublics.get(0).getPkey())) {
                        ErrorConsts.CANCEL_MODIFY_ORDER_ITEM_ERROR.throwOut();
                    }
                }
            }
        }
    }

    private boolean isInvalid(WithdrawOrderRequest request, OrderItem orderItem) {
        String operType = orderItem.getOperType();
        String serviceOfferId = orderItem.getServiceOfferId();
        String operTypes = "/" + CoreDataInteract.EVT_C_0003_1700 + "/" + CoreDataInteract.EVT_C_0003_1400 + "/"
            + CoreDataInteract.EVT_C_0003_1800 + "/" + CoreDataInteract.EVT_C_0003_1801 + "/"
            + CoreDataInteractLocal.EVT_C_0003_2300 + "/";
        if (KiteStringUtils.isNotEmpty(operType)) {
            // 缓装，待装, 缓装激活，待装激活, 差错回单，认为是有效
            if (operTypes.indexOf("/" + operType + "/") > -1) {
                return Boolean.FALSE;
            }
        }

        // TODO 待确认是否需要
        /*
         * if (this.isInValidFlag()) { return true; }
         */

        if (KeyValuesLocal.SERVICE_OFFER_ISMP_REMV.equals(serviceOfferId)
            || KeyValuesLocal.SERVICE_OFFER_ISMP_INST.equals(serviceOfferId)) {
            return Boolean.FALSE;
        }

        // 改为dc_system_param配置
        String skipServiceId = DcSystemParamCache.getDcParamVal(KeyConsts2.WITHDRAW_SKIP_SERVICE_ID);
        if (KiteStringUtils.isNotEmpty(skipServiceId)
            && Arrays.asList(skipServiceId.split(",")).contains(serviceOfferId)) {
            return Boolean.FALSE;
        }

        // 不需要取变动信息，直接生成订单的服务提供改成可配置
        String skipServiceOfferId = DcPublicCache.getCodea(IKeyValues.DC_PUBLIC_STYPE_2721003, serviceOfferId);
        if (!KiteStringUtils.isEmpty(skipServiceOfferId)) {
            return Boolean.FALSE;
        }

        // 资源割接单,资源变更单不需要变动信息,但是也是属于有效的订单,这样的单子不需要送计费.
        if (KeyValuesLocal.SERVICE_OFFER_ZYGJ.equals(serviceOfferId)
            || KeyValuesLocal.SERVICE_OFFER_ZYBG.equals(serviceOfferId)) {
            return Boolean.FALSE;
        }

        // 如果是更换光猫的服务，不需要变动信息，认为是有效单
        if (KeyValuesLocal.SERVICE_OFFER_GHGM.equals(serviceOfferId)) {
            return Boolean.FALSE;
        }

        // 用于新购预存款信息回调产品页面修改
        if ((!KiteListUtils.isEmpty(request.getOrderContainer().getOrderDepositMap().get(orderItem.getOrderItemId())))
            && (KeyValuesLocal.SERVICE_OFFER_INSTALL.equals(serviceOfferId))) {
            return Boolean.FALSE;
        }

        // 撤单，且不过开通，则认为是有效的工单。
        if (KeyValues.SKIP_OPEN_U.equals(orderItem.getSkipOpen())) {
            return Boolean.FALSE;
        }

        // return isEmpty(); TODO 待确认，这里应该不会为空了
        return Boolean.FALSE;
    }

    @Override
    public void loadOldOrderItems(WithdrawOrderRequest request) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mergeOldOrderItems(WithdrawOrderRequest request) {
        // TODO Auto-generated method stub

    }

    @Override
    public void loadInsts(WithdrawOrderRequest request) {
        // TODO Auto-generated method stub

    }

    @Override
    public void createWithdrawOrderItems(WithdrawOrderRequest request) {
        // TODO Auto-generated method stub

    }

    @Override
    public void saveWithdrawOrderItems(WithdrawOrderRequest request) {
        // TODO Auto-generated method stub

    }

    @Override
    public void createWithdrawOrderItemChanges(WithdrawOrderRequest request) {
        // TODO Auto-generated method stub

    }

    @Override
    public void saveWithdrawOrderItemChanges(WithdrawOrderRequest request) {
        // TODO Auto-generated method stub

    }

    @Override
    public void updateInsts(WithdrawOrderRequest request) {
        // TODO Auto-generated method stub

    }

    @Override
    public void clearBackfillStaffId(WithdrawOrderRequest request) {
        String custId = null;
        List<String> clearOrderItemIds = new ArrayList<>();

        Iterator<OrderItem> it = OrderContainer.ofRequest(request).listOrderItems().iterator();
        while (it.hasNext()) {
            OrderItem orderItem = it.next();
            if (KiteStringUtils.isEmpty(custId)) {
                custId = orderItem.getBelongCustId();
            }
            // 已生成撤单订单项，这里取旧订单项ID
            String oldOrderItemId = orderItem.getOldOrderItemId();
            String backfillStaffId = orderItem.getBackfillStaffId();
            if (!KiteStringUtils.isEmpty(backfillStaffId)) {
                clearOrderItemIds.add(oldOrderItemId);
            }
        }
        if (!KiteListUtils.isEmpty(clearOrderItemIds)) {
            this.orderItemMapper.clearBackfillStaffId(clearOrderItemIds, custId);
        }
    }

    @Override
    public void createWithdrawAcctItems(WithdrawOrderRequest request) {
        // TODO Auto-generated method stub

    }

    @Override
    public void saveWithdrawAcctItems(WithdrawOrderRequest request) {
        // TODO Auto-generated method stub

    }

    @Override
    public void deleteOrderItems(WithdrawOrderRequest request) {
        List<OrderItem> deleteOrderItems = request.getDeleteOrderItems();
        if (KiteListUtils.isEmpty(deleteOrderItems)) {
            List<String> orderItemIds = new ArrayList<>();
            deleteOrderItems.forEach((orderItem) -> orderItemIds.add(orderItem.getOrderItemId()));

            String custId = deleteOrderItems.get(0).getBelongCustId();
            // 删除发展人
            Example devExample = new Example(DevStaffInfo.class);
            devExample.createCriteria().andEqualTo("orderType", KeyConsts2.ORDER_TYPE_ORDERITEM)
                .andIn("orderItemId", orderItemIds).andEqualTo("custId", custId);
            this.devStaffInfoMapper.deleteByExample(devExample);
            // 删除联系人
            Example contactExample = new Example(OrderContactInfo.class);
            contactExample.createCriteria().andEqualTo("orderType", KeyConsts2.ORDER_TYPE_ORDERITEM)
                .andIn("orderItemId", orderItemIds).andEqualTo("custId", custId);
            this.orderContactInfoMapper.deleteByExample(contactExample);
            // 删除order_deposit表数据
            Example depositExample = new Example(OrderDeposit.class);
            depositExample.createCriteria().andIn("orderItemId", orderItemIds).andEqualTo("custId", custId);
            orderDepositMapper.deleteByExample(depositExample);
            // 删除order_item_rel表数据
            Example orderItemRelExample = new Example(OrderItemRel.class);
            orderItemRelExample.createCriteria().andIn("orderItemId", orderItemIds).andEqualTo("custId", custId);
            orderItemRelMapper.deleteByExample(orderItemRelExample);
            // 删除order_item_attr表数据
            // Example orderItemAttrExample = new Example(OrderItemAttr.class);
            // orderItemAttrExample.createCriteria().andIn("orderItemId", orderItemIds).andEqualTo("custId", custId);
            // orderItemAttrMapper.deleteByExample(orderItemAttrExample);
            // 删除变动信息
            Example orderItemChangeExample = new Example(OrderItemChange.class);
            orderItemChangeExample.createCriteria().andIn("orderItemId", orderItemIds).andEqualTo("custId", custId);
            orderItemChangeMapper.deleteByExample(orderItemChangeExample);
            // 删除订单项的费用信息

        }
    }

    @Override
    public void deleteApprove(String orderItemId, String custId) {

    }

    @Override
    public void deleteRecycleInfo(String custOrderId, String objId, String custId) {

    }

    @Override
    public void clearReason(String custOrderId, String custId) {
        Example example = new Example(OrderItem.class);
        example.createCriteria().andEqualTo("custOrderId", custOrderId)
            .andIn("statusCd", Arrays.asList(CoreDataInteract.EVT_0001_101100, CoreDataInteract.EVT_0001_101300))
            .andEqualTo("belongCustId", custId);
        int count = this.orderItemMapper.selectCountByExample(example);
        if (count == 0) {
            this.customerOrderMapper.clearReason(custOrderId, custId);
        }
    }

}
